package com.nai365.nart.operation.service.impl;

import com.nai365.nart.common.core.constant.SecurityConstants;
import com.nai365.nart.common.core.util.R;
import com.nai365.nart.operation.dto.SpuDto;
import com.nai365.nart.operation.service.ProductService;
import com.nai365.nart.product.api.feign.RemoteCategoryService;
import com.nai365.nart.product.api.feign.RemoteSkuService;
import com.nai365.nart.product.api.feign.RemoteSpuService;
import com.nai365.nart.product.entity.Category;
import com.nai365.nart.product.entity.SkuInfo;
import com.nai365.nart.product.entity.SpuInfo;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
@AllArgsConstructor
public class ProductServiceImpl implements ProductService {

	private final RemoteSpuService remoteSpuService;

	private final RemoteCategoryService remoteCategoryService;

	private final RemoteSkuService remoteSkuService;

	@Override
	public SpuInfo findSpuById(Long id) {
		R<SpuInfo> remoteSpu = remoteSpuService.getById(id, SecurityConstants.FROM_IN);
		SpuInfo spuInfo = null;
		if (remoteSpu.getCode() == 0 && remoteSpu.getData() != null) {
			spuInfo = remoteSpu.getData();
		}
		return spuInfo;
	}

	public Map<Long, SpuDto> getSpuInfoMapByIds(List<Long> ids) {
		Map<Long, SpuDto> result = new HashMap<>();
		R<List<SpuInfo>> remoteResult = this.remoteSpuService.listByIds(ids, SecurityConstants.FROM_IN);
		Map<Long, Category> categoryMap = this.getAllCategoryMap();
		if (remoteResult.getCode() == 0 && remoteResult.getData() != null && !remoteResult.getData().isEmpty()) {
			for (SpuInfo spu : remoteResult.getData()) {
				SpuDto dto = new SpuDto();
				BeanUtils.copyProperties(spu, dto);
				Category category = categoryMap.get(dto.getCatalogId());
				if (category != null) {
					dto.setCatalogName(category.getName());
					dto.setFullCatalogName(getFullCatalogName(categoryMap, category));
				}
				result.put(spu.getId(), dto);
			}
		}
		return result;
	}

	private String getFullCatalogName(Map<Long, Category> categoryMap, Category category) {
		String result = category.getName();
		while (category.getParentCid() != null && category.getParentCid() > 0) {
			category = categoryMap.get(category.getParentCid());
			result = category.getName() + "/";
		}
		return result;
	}

	public Map<Long, Category> getAllCategoryMap() {
		Map<Long, Category> result = new HashMap<>();
		R<List<Category>> remoteResult = this.remoteCategoryService.listAll(SecurityConstants.FROM_IN);
		if (remoteResult.getCode() == 0 && remoteResult.getData() != null && !remoteResult.getData().isEmpty()) {
			for (Category category : remoteResult.getData()) {
				result.put(category.getCatId(), category);
			}
		}
		return result;
	}

	@Override
	public List<SkuInfo> findMySkuBySpuIdAndStatus(Long spuId, Integer status) {
		List<SkuInfo> result = new ArrayList<>();
		R<List<SkuInfo>> remote = remoteSkuService.findMySkuBySpuIdAndStatus(spuId, status);
		if (remote.getCode() == 0 && remote.getData() != null) {
			result = remote.getData();
		}
		return result;
	}

	@Override
	public List<SkuInfo> findSkuByIds(Collection<Long> ids) {
		List<SkuInfo> result = new ArrayList<>();
		R<List<SkuInfo>> remote = remoteSkuService.infos(ids, SecurityConstants.FROM_IN);
		if (remote.getCode() == 0 && remote.getData() != null) {
			result = remote.getData();
		}
		return result;
	}

	@Override
	public SkuInfo lockSkuInfo(Long spuId) throws Exception {
		R<SkuInfo> remote = remoteSkuService.lockSkuInfo(spuId);
		if (remote.getCode() == 0 && remote.getData() != null) {
			return remote.getData();
		}
		throw new Exception(remote.getMsg());
	}

	@Override
	public SkuInfo unLockSkuInfo(SkuInfo skuInfo) throws Exception {
		R<SkuInfo> remote = remoteSkuService.unLockSkuInfo(skuInfo);
		if (remote.getCode() == 0 && remote.getData() != null) {
			return remote.getData();
		}
		throw new Exception(remote.getMsg());
	}

	@Override
	public void updateSku(SkuInfo skuInfo) {
		this.remoteSkuService.updateById(skuInfo);
	}

	@Override
	public void updateSkuInner(SkuInfo skuInfo) {
		this.remoteSkuService.updateByIdInner(skuInfo, SecurityConstants.FROM_IN);
	}

	@Override
	public List<SkuInfo> updateBatchSkuInfo(List<SkuInfo> skuInfoList) throws Exception {
		R<List<SkuInfo>> remote = remoteSkuService.updateBatch(skuInfoList);
		if (remote.getCode() == 0 && remote.getData() != null && !remote.getData().isEmpty()) {
			return remote.getData();
		}
		throw new Exception(remote.getMsg());
	}

	@Override
	public SkuInfo findSkuById(Long id) throws Exception {
		R<SkuInfo> remote = remoteSkuService.getById(id);
		if (remote.getCode() == 0 && remote.getData() != null) {
			return remote.getData();
		}
		throw new Exception(remote.getMsg());
	}

	@Override
	public SkuInfo findSkuByIdInner(Long id) throws Exception {
		R<SkuInfo> remote = remoteSkuService.getByIdInner(id, SecurityConstants.FROM_IN);
		if (remote.getCode() == 0 && remote.getData() != null) {
			return remote.getData();
		}
		throw new Exception(remote.getMsg());
	}
}
